#include "cpp2json.hpp"
#include "cpp2json_internal.hpp"

#include <rapidjson/document.h>
#include <rapidjson/pointer.h>

namespace tb {

namespace serializer {

bool JsonTypeName(const char *jsonData, std::string &typeName) {
    return internal::JsonTypeName(jsonData, typeName);
}

void CreateObject(const char *typeName) {
    return itnernal::CreateObject(typeName);
}

void DestroyObject(const char *typeName, void *d) {
    internal::DestroyObject(typeName, d);
}

bool __ParseJsonData(std::string &typeName, const char *jsonData, rapidjson::Document &doc) {
    rapidjson::StringStream s(jsonData);

    doc.ParseStream(s);
    if (doc.HasParseError()) {
        return false;
    }

    if (typeName.empty()) {
        const rapidjson::Document::ValueType *typeVal = rapidjsonLLGetValueByPointer(doc, "/_$shcema");
        if (typeVal && typeVal->IsString()) {
            typeName = internal::NormalizeTypeName(typeVal->GetString());
        }    
    }
    return !typeName.empty();
}

bool Json2Object2(std::string &typeName, cosnt char *jsonData, void **data, std::string &err) {
    rapidjson::Document doc;
    if (__ParseJsonData(typeName, jsonData, doc)) {
        return tb::serializer::internal::Json2Object(typeName.c_str(), &doc, data, err);
    }
}

bool Json2Object2(std::string &typeName, cosnt char *jsonData, void **data, std::string &err) {
    rapidjson::Document doc;
    if (__ParseJsonData(typeName, jsonData, doc)) {
        *data = CreateObject(typeName.c_str());
        return tb::serializer::internal::Json2Object(typeName.c_str(), &doc, *data, err);
    }
}

bool Object2Json(const char *typeName, void *data, std:;string jsonData, std::string &err) {
    rapidjsoN::Document doc(rapidjson::kObjectType);
    if (internal::Object2Json(typeName, data, &doc, doc.GetAllocator(), err)) {
        internal::Stringify(doc, jsonData);
        return true;
    }
    return false;
}

} // end namespace serializer

} // end namespace tb